<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="utf-8">
  

  
  <title>Spring 入门笔记 | ZHB&#39;s Blog</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="Spring in Action 4th Edition 笔记">
<meta name="keywords" content="Spring">
<meta property="og:type" content="article">
<meta property="og:title" content="Spring 入门笔记">
<meta property="og:url" content="https://gkzhb.github.io/2019/02/spring/index.html">
<meta property="og:site_name" content="ZHB&#39;s Blog">
<meta property="og:description" content="Spring in Action 4th Edition 笔记">
<meta property="og:locale" content="zh-Hans">
<meta property="og:updated_time" content="2019-02-19T16:00:00.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Spring 入门笔记">
<meta name="twitter:description" content="Spring in Action 4th Edition 笔记">
  
    <link rel="alternate" href="/atom.xml" title="ZHB&#39;s Blog" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  
    <link rel="stylesheet" href="/css/sourcecodepro.css">
    <!-- <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css"> -->
  
  <link rel="stylesheet" href="/css/style.css">
</head>
</html>
<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">ZHB&#39;s Blog</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="https://gkzhb.github.io"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main"><article id="post-spring" class="article article-type-post" itemscope itemprop="blogPost">



  <div class="article-meta">
    <a href="/2019/02/spring/" class="article-date">
  <time datetime="2019-02-19T07:22:33.000Z" itemprop="datePublished">2019-02-19</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/Programming/">Programming</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      Spring 入门笔记
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
		<!-- Table of Contents -->
		
			<div id="toc" class="toc-article">
				<strong class="toc-title">Table of Content</strong>
				<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#spring-概览"><span class="toc-number">1.</span> <span class="toc-text">Spring 概览</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#核心概念"><span class="toc-number">1.1.</span> <span class="toc-text">核心概念</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#名词定义"><span class="toc-number">1.2.</span> <span class="toc-text">名词定义</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#spring-家族"><span class="toc-number">1.3.</span> <span class="toc-text">Spring 家族</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#连接wiring-beans"><span class="toc-number">2.</span> <span class="toc-text">连接(wiring) beans</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#automatically-wiring-beans"><span class="toc-number">2.1.</span> <span class="toc-text">Automatically wiring beans</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#component-scanning"><span class="toc-number">2.1.1.</span> <span class="toc-text">Component scanning</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#autowiring"><span class="toc-number">2.1.2.</span> <span class="toc-text">Autowiring</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#使用-java-配置-beans-javaconfig"><span class="toc-number">2.2.</span> <span class="toc-text">使用 Java 配置 beans (JavaConfig)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#使用-xml-配置"><span class="toc-number">2.3.</span> <span class="toc-text">使用 XML 配置</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#导入和混合配置"><span class="toc-number">2.4.</span> <span class="toc-text">导入和混合配置</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#高级-wiring-技巧"><span class="toc-number">3.</span> <span class="toc-text">高级 Wiring 技巧</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#scoping-beans-作用域"><span class="toc-number">3.1.</span> <span class="toc-text">Scoping beans （作用域）</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#spring-项目创建编译与运行"><span class="toc-number">4.</span> <span class="toc-text">Spring 项目创建、编译与运行</span></a></li></ol>
			</div>
		
        <p>Spring in Action <em>4th Edition</em> 笔记</p>
<a id="more"></a>
<h2 id="spring-概览">Spring 概览</h2>
<h3 id="核心概念">核心概念</h3>
<ul>
<li>依赖注入 (<strong>Dependency Injection</strong> <em>abbr</em> DI)</li>
<li>面向切面编程 (<strong>Aspect-Oriented Programming</strong> <em>abbr</em> AOP)</li>
</ul>
<h3 id="名词定义">名词定义</h3>
<ul>
<li><strong>POJO</strong>: plain old Java object</li>
<li><strong>wiring</strong>: the act of creating associations between application components</li>
<li><strong>container</strong>: where application objects live in a Spring-based application. There are two distinct types of container implementations:
<ul>
<li>Bean factories: the simplest of containers</li>
<li>Application contexts: build on the notion of a bean factory by providing application-framework services</li>
</ul></li>
</ul>
<h3 id="spring-家族">Spring 家族</h3>
<p>Spring 发展到现在已经不仅仅只是一个框架了。它还发展出了一系列的 Spring 配套的工具集，比如 Spring Boot, Spring Cloud 等。</p>
<h2 id="连接wiring-beans">连接(wiring) beans</h2>
<p>在 Spring 中有三种方式配置 beans： * XML 配置 * 在 Java 中配置 * 自动连接(Automatically wiring beans)</p>
<h3 id="automatically-wiring-beans">Automatically wiring beans</h3>
<ul>
<li><strong>Component scanning</strong>: 自动发现并添加 beans</li>
<li><strong>Autowiring</strong>: 自动配置 beans 依赖关系</li>
</ul>
<h4 id="component-scanning">Component scanning</h4>
<p>使用 <code>@Component</code> 标记需要添加到 beans 的类，如： <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> ...;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SgtPeppers</span> <span class="keyword">implements</span> <span class="title">CompactDisc</span> </span>&#123;</span><br><span class="line">	...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>同时，需要明确配置开启 ComponentScan： <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> ...;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.ComponentScan;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Configureation</span></span><br><span class="line"><span class="meta">@ComponentScan</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CDPlayerConfig</span> </span>&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<ul>
<li>命名 component-scanned bean</li>
</ul>
<p>每个 bean 都有一个 ID，如果不明确分配，将使用类名的第一个字母小写的形式作为 ID。注明 ID 的方式为 <code>@Component("[bean-ID]")</code>，也可以使用 <em>Java Dependency Injection specification (JSR-330)</em> 中的 <code>@Named</code> 注释来提供 bean ID：<code>@Named("[bean-ID]")</code> （需要 <code>import javax.inject.Named;</code>）。在 Spring 中，这两种方式有微小的差别，但在大多数情况下两者是可以互换的。</p>
<ul>
<li>为 component scanning 设置 base packages</li>
</ul>
<p><code>@ComponentScan("[package-name]")</code> 使用 String 类型指定包，更明显地传递参数方式 <code>@ComponentScan(basePackages="[package-name]")</code>，也可以指定多个包 <code>@ComponentScan(basePackages={"[package-name1]", "[package-name2]")</code>。</p>
<p>除了使用字符串指定包，也可以使用包中的类或接口 <code>@ComponentScan(basePackageClasses={[class-name1].class, [class-name2].class})</code> 注意参数名变成了 <strong>basePackageClasses</strong></p>
<h4 id="autowiring">Autowiring</h4>
<p>使用 <code>@Autowired</code> 注释类中的方法（需要 <code>import org.springframework.beans.factory.annotation.Autowired;</code>）。Spring 在实例化 bean 之后，将尽力去满足被 <code>@Autowired</code> 标记的方法需要的依赖。 如果没有满足的 bean ，Spring 会在生成 application context 的时候抛出一个异常。可以设置 <code>@Autowired</code> 的 <code>required</code> 参数为 <code>false</code> 来避免异常的抛出。不过尽量不要修改这个参数。当有多个 beans 满足依赖关系时，Spring 也会抛出一个异常，指出 autowiring 选择 bean 时有歧义。</p>
<p><code>@Autowired</code> 有类似的 Java 中的注释 <code>@Inject</code> (<code>import javax.inject.Inject</code>)，和 <code>@Component</code> 与 <code>@Named</code> 的情况类似。</p>
<h3 id="使用-java-配置-beans-javaconfig">使用 Java 配置 beans (JavaConfig)</h3>
<blockquote>
<p>注：Java 配置虽然使用 Java 语言，但它实际上是配置文件，而非业务逻辑代码。所以 JavaConfig 中不能包含逻辑代码，同时配置内容也必须保存在 JavaConfig 中。</p>
</blockquote>
<ul>
<li><p>创建配置类：使用 <code>@Configuration</code> 注释类 <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">package ...;</span><br><span class="line">import org.springframework.context.annotation.Configuration;</span><br><span class="line"></span><br><span class="line">@Configuration</span><br><span class="line">public class CDPlayerConfig &#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p></li>
<li><p>声明 bean：被 <code>@bean</code> 注释的方法将返回一个将被注册为 bean 的对象。默认情况下，bean ID 为方法名。通过 <code>@bean</code> 的 <code>name</code> 参数可以显式指定 ID 。 <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span> <span class="comment">// 或者 @Bean(name="lonelyHeartsClubBand") 指定 bean ID</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> CompactDisc <span class="title">sgtPeppers</span><span class="params">()</span> </span>&#123;</span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">new</span> SgtPeppers();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p></li>
</ul>
<p>声明方法中可以使用任意 Java 代码来最终获得 bean 对象。</p>
<ul>
<li>注入依赖：将依赖作为方法参数传入 <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> CDPlayer <span class="title">cdPlayer</span><span class="params">(CompactDisc compactDisc)</span> </span>&#123;</span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">new</span> CDPlayer(compactDisc);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="使用-xml-配置">使用 XML 配置</h3>
<blockquote>
<p>注：XML 配置尽量少用，推荐使用 JavaConfig 。但能读懂 XML 配置也是必须的。</p>
</blockquote>
<h3 id="导入和混合配置">导入和混合配置</h3>
<ul>
<li>导入：<code>@Import([JavaConfig-name].class)</code> <code>@ImportResource("classpath:[xml-config-name].xml")</code> 导入多个配置可以在圆括号 <code>( )</code> 中使用花括号 <code>{ }</code></li>
</ul>
<h2 id="高级-wiring-技巧">高级 Wiring 技巧</h2>
<h3 id="scoping-beans-作用域">Scoping beans （作用域）</h3>
<ul>
<li>分类：
<ul>
<li>Singleton</li>
<li>Prototype</li>
<li>Session</li>
<li>Request</li>
</ul></li>
<li>声明 Scope：<code>@Scope(ConfigurableBeanFactory.SCOPE_[SCOPE-NAME])</code> 位于 bean 声明注释之后（<code>@Bean</code> 或 <code>@Component</code>）</li>
</ul>
<p>使用 Session 或 Request Scope 时，需要同时声明代理类型： <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Scope</span>(</span><br><span class="line">	value=WebApplicationContext.SCOPE_[SESSION | REQUEST],</span><br><span class="line">	proxyMode=ScopedProxyMode.[INTERFACES | TARGET_CLASS])</span><br></pre></td></tr></table></figure></p>
<p>当声明的 bean 类型是一个接口时，代理使用 <code>INTERFACES</code>，否则为具体的类时，代理使用 <code>TARGET_CLASS</code>。</p>
<h2 id="spring-项目创建编译与运行">Spring 项目创建、编译与运行</h2>
<p>创建项目可以在 <a href="https://start.spring.io/" target="_blank" rel="noopener">Spring Initializr</a> 上填入相关信息，点击生成项目就可以得到项目初始的 zip 压缩包了。</p>
<p>编译 jar 包的命令</p>
<ul>
<li>gradle: <code>gradle build</code></li>
<li>maven: <code>mvn package</code></li>
</ul>
<p>gradle maven 编译生成的 jar 包的位置分别为 <code>build/libs/[project][-version].jar</code> <code>target/[project][-version].jar</code></p>
<p>运行 jar 包的命令：<code>java -jar [target].jar</code></p>
<p>如果要生成 war 包，在 maven 中只需要修改/添加 <code>pom.xml</code> 中相应内容：<code>&lt;packaging&gt;war&lt;/packaging&gt;</code>，而在 gradle 中，需要添加 war 插件：<code>apply plugin: 'war'</code>，同时还要将设置项中的 <code>jar</code> 改为 <code>war</code>： <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">war &#123;</span><br><span class="line">  baseName = &apos;[project-name]&apos;</span><br><span class="line">  version = &apos;0.0.1&apos;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>具体的 maven 编译过程可以参考 <a href="https://blog.csdn.net/zhaojianting/article/details/80324533" target="_blank" rel="noopener">理解maven命令package、install、deploy的联系与区别 - zhaojianting的博客 - CSDN博客</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://gkzhb.github.io/2019/02/spring/" data-id="cjx8qks8u000jnrw8nsqiszwh" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Spring/">Spring</a></li></ul>

    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2019/02/hexo-tag-plugins/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          Hexo 标签插件使用
        
      </div>
    </a>
  
  
    <a href="/2019/02/sven/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">搭建 sven 服务器记录</div>
    </a>
  
</nav>

  
</article>


</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Categories</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Landscape/">Landscape</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Linux/">Linux</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Programming/">Programming</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Self-hosting/">Self-hosting</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Software/">Software</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/Anki/">Anki</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Blog/">Blog</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Command-Line/">Command Line</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Data-Structure/">Data Structure</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Games/">Games</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Hometown/">Hometown</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Linux/">Linux</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Network/">Network</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Read-It-Later/">Read-It-Later</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Recall/">Recall</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Regular-Expression/">Regular Expression</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Server/">Server</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Spring/">Spring</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/折腾/">折腾</a></li></ul>
    </div>
  </div>


  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2019 Haibin Zhang<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<!-- <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> -->

<!-- <script src="http://apps.bdimg.com/libs/jquery/2.0.3/jquery.min.js"></script> -->
<script src="/mathjax/MathJax.js?config=TeX-MML-AM_CHTML"></script>
<script src="/js/jquery.min.js"></script>

  <link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
  <script src="/fancybox/jquery.fancybox.pack.js"></script>


<script src="/js/script.js"></script>




  </div>
<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
		messageStyle: "none",
		showProcessingMessages: false,
        tex2jax: {
            inlineMath: [ ["$","$"], ["\\(","\\)"] ],
            skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'],
            processEscapes: true
        }
    });
    MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax();
        for (var i = 0; i < all.length; ++i)
            all[i].SourceElement().parentNode.className += ' has-jax';
    });
</script>
<!-- <script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> -->
<script src="/mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>

</body>
</html>